import errorCodesBuilder from '../../helpers/errorCodesBuilder';
import {
	TASK_KEY_LABEL_MAP,
	SSL_CATEGORY_KEY_LABEL_MAP,
} from '../../../common/constants';
import warningCounts from '../../helpers/warningCounts';
const errorCodes = errorCodesBuilder('忽略告警失败');

const detailBuilder = ({ task, warnArr, titleText, isResolved }) => {
	switch (task.taskType) {
		case 'vul':
			return `更新资产地址${task.target}的${
				TASK_KEY_LABEL_MAP[task.taskType]
			}“${warnArr.map(x => x.title).join('、')}”状态为已忽略。`;
		case 'ssl':
			return `更新资产地址${task.target}的${
				TASK_KEY_LABEL_MAP[task.taskType]
			}“${warnArr
				.map(x => `${SSL_CATEGORY_KEY_LABEL_MAP[x.category]}：${x.title}`)
				.join('、')}”状态为已忽略。`;
		case 'securityEvent':
			return `更新资产地址${task.target}的风险URL${warnArr
				.map(x => x.affects)
				.join('、')}状态为已忽略`;
		default:
			return '';
	}
};

const AUDIT_LOG_TITLE_MAP = {
	vul: '漏洞',
	ssl: '漏洞',
	securityEvent: '风险',
	asset: '资产',
};
export default {
	description: '忽略告警',
	type: 'Task',
	args: {
		taskId: 'MongoID!',
		warnIds: '[String]!',
	},
	async resolve(root, { taskId, warnIds }, { request }) {
		const {
			server: {
				app: {
					model: { Task, Job },
				},
			},
			auth: {
				credentials: { uid, permissionMap },
			},
		} = request;

		let task;
		try {
			const query = { _id: taskId };
			if (!permissionMap[`cloud-monitor\x01editTask\x010`]) {
				query.uid = uid;
			}
			task = await Task.findOne(query);
		} catch (err) {
			const error = errorCodes['[01]忽略告警:查找任务mongo记录失败'].from(err);
			request.log.error({ error }, error.rawMessage);
			throw error;
		}

		if (!task) {
			const error = errorCodes['[01]忽略告警:没有找到对应mongo记录'];
			request.log.error({ taskId, warnIds }, error.internalMessage);
			throw error;
		}

		if (!task.isLatestTask) {
			const error = errorCodes['[01]忽略告警:不能修改非最后一次任务状态'];
			request.log.error({ error }, error.rawMessage);
			throw error;
		}

		const job = task.refId;
		const warnArr = [];
		const jobUpdateFields = {};
		const warnIdMap = warnIds.reduce((obj, x) => {
			obj[x] = true;
			return obj;
		}, {});
		task.result.warnings = task.result.warnings.map(x => {
			if (warnIdMap[x.id]) {
				warnArr.push(x);
				x.ignoredTime = new Date();
				x.isResolved = false;
				jobUpdateFields[`ignoredWarnIdMap.${x.id}`] = x.ignoredTime;
			}
			return x;
		});
		Object.assign(task.result, warningCounts(task.result.warnings));
		if (task.result.warnings.every(x => x.ignoredTime || x.isResolved)) {
			// 所有异常都解决或忽略
			task.securityStatus = 'safe';
		}

		try {
			task.refId = job._id;
			await Promise.all([
				task.save(),
				Job.updateOne({ _id: task.jobId }, { $set: jobUpdateFields }),
			]);
		} catch (err) {
			const error = errorCodes['[01]忽略告警：更新mongo记录失败'].from(err);
			request.log.error({ error }, error.rawMessage);
			throw error;
		}

		request.log.audit(
			{
				affects: [task.target],
				module: 'task',
				actionType: 'update',
				actionMessage: `更新${AUDIT_LOG_TITLE_MAP[task.taskType]}状态`,
				detail: detailBuilder({ task, warnArr }),
			},
			`[${task.target}]忽略告警`
		);

		return task;
	},
};
